Edit January 11th, 2016: using ggrepel package with ggplot2 v2.0.0 and ggmap v2.6
ggrepel works well. The geom_label_repel() code below shows some of the available options.
lat <- c(47.597157,47.656322,47.685928,47.752365,47.689297,47.628128,47.627071, 47.586349,47.512684,47.571232,47.562283) lon <- c(-122.312187,-122.318039,-122.31472,-122.345345,-122.377045,-122.370117, -122.368462,-122.331734,-122.294395,-122.33606,-122.379745) labels <- c("Site 1A","Site 1B","Site 1C","Site 2A","Site 3A","Site 1D", "Site 2C","Site 1E","Site 2B","Site 1G","Site 2G") df <- data.frame(lat,lon,labels) library(ggmap) library(ggrepel) library(grid) map.data <- get_map(location = c(lon = -122.3485, lat = 47.6200), maptype = 'roadmap', zoom = 11) ggmap(map.data) + geom_point(data = df, aes(x = lon, y = lat), alpha = 1, fill = "red", pch = 21, size = 5) + labs(x = 'Longitude', y = 'Latitude') + geom_label_repel(data = df, aes(x = lon, y = lat, label = labels), fill = "white", box.padding = unit(.4, "lines"), label.padding = unit(.15, "lines"), segment.color = "red", segment.size = 1)

Original answer, but updated for ggplot v2.0.0 and ggmap v2.6
If there is only a small number of overlapping points, then using the top.bumpup or top.bumptwice method from the direct label package can separate them. In the code below, I use the geom_dl() function to create and place labels.
lat <- c(47.597157,47.656322,47.685928,47.752365,47.689297,47.628128,47.627071, 47.586349,47.512684,47.571232,47.562283) lon <- c(-122.312187,-122.318039,-122.31472,-122.345345,-122.377045,-122.370117, -122.368462,-122.331734,-122.294395,-122.33606,-122.379745) labels <- c("Site 1A","Site 1B","Site 1C","Site 2A","Site 3A","Site 1D", "Site 2C","Site 1E","Site 2B","Site 1G","Site 2G") df <- data.frame(lat,lon,labels) library(ggmap) library(directlabels) map.data <- get_map(location = c(lon = -122.3485, lat = 47.6200), maptype = 'roadmap', zoom = 11) ggmap(map.data) + geom_point(data = df, aes(x = lon, y = lat), alpha = 1, fill = "red", pch = 21, size = 6) + labs(x = 'Longitude', y = 'Latitude') + geom_dl(data = df, aes(label = labels), method = list(dl.trans(y = y + 0.2), "top.bumptwice", cex = .8, fontface = "bold", family = "Helvetica"))

Edit: setting for base tags
Several spring methods, but none of them are completely satisfactory. But I do not think that you will find a solution that will apply to all situations.
Adding a background color for each label
This is a bit of a workaround, but directlabels has a "box" function (ie. Labels are placed inside the field). It looks like you have the option to change the background fill and border color in the list in geom_dl , but I can't get it to work. Instead, I take two functions ( draw.rects and enlarge.box ) from the directlabels website; modify them; and combine the changed functions with the "top.bumptwice" method.
draw.rects.modified <- function(d,...){ if(is.null(d$box.color))d$box.color <- NA if(is.null(d$fill))d$fill <- "grey95" for(i in 1:nrow(d)){ with(d[i,],{ grid.rect(gp = gpar(col = box.color, fill = fill), vp = viewport(x, y, w, h, "cm", c(hjust, vjust=0.25), angle=rot)) }) } d } enlarge.box.modified <- function(d,...){ if(!"h"%in%names(d))stop("need to have already calculated height and width.") calc.borders(within(d,{ w <- 0.9*w h <- 1.1*h })) } boxes <- list("top.bumptwice", "calc.boxes", "enlarge.box.modified", "draw.rects.modified") ggmap(map.data) + geom_point(data = df,aes(x = lon, y = lat), alpha = 1, fill = "red", pch = 21, size = 6) + labs(x = 'Longitude', y = 'Latitude') + geom_dl(data = df, aes(label = labels), method = list(dl.trans(y = y + 0.3), "boxes", cex = .8, fontface = "bold"))

Add a schema for each label
Another option is to use this method to give each shortcut an outline, although it is not immediately clear how it will work with directlabels. Therefore, for this you will need to manually adjust the coordinates or search for a data frame for coordinates that are in a given threshold, then adjust. However, here I use the pointLabel function from the maptools package to place labels. There is no guarantee that it will work every time, but I got a reasonable result with your data. A random element is built into it, so you can run it several times until you get a reasonable result. Also note that it places labels in the base chart. Then the tags should be retrieved and loaded into ggplot / ggmap.
lat<- c(47.597157,47.656322,47.685928,47.752365,47.689297,47.628128,47.627071,47.586349,47.512684,47.571232,47.562283) lon<-c(-122.312187,-122.318039,-122.31472,-122.345345,-122.377045,-122.370117,-122.368462,-122.331734,-122.294395,-122.33606,-122.379745) labels<-c("Site 1A","Site 1B","Site 1C","Site 2A","Site 3A","Site 1D","Site 2C","Site 1E","Site 2B","Site 1G","Site 2G") df<-data.frame(lat,lon,labels) library(ggmap) library(maptools)
