How about calculating a "density" value for each pixel to start with, based on its proximity to all the other pixels. Then, repeatedly remove the most "dense" pixel until you're below p% remaining in the list.
You'd need to do the distance calculation to determine density between any given two points at most twice. First time would be when you build the original list - each pixel would need to be compared with each other pixel. Second would be when you remove a pixel from the list - you'd have to calculate the removed one against each one remaining in the list. This is to account for density values changing as each pixel is removed - for example, 2 pixels directly next to each other would have a very very high value, but once one is removed, the remaining one might have a very low value.
Some quick pseudocode (note that in this example, higher density areas have a low number)
For I = 0 to MaxPixel
For J = I to MaxPixel
PixelDensity[I], PixelDensity[J] += DistanceBetween(Pixels[I], Pixels[J])
While PixelDensity.Count > TargetCount
RemovePixel = IndexOfSmallest(PixelDensity)
ForEach I in PixelDensity
PixelDensity[I] -= DistanceBetween(Pixels[I], Pixels[RemovePixel])
PixelDensity.Remove(RemovePixel)
If memory is less of a concern than calculation time, you can also store the distance between any two points in a simple 2d array. Also, instead of simple distance, it might be helpful to make the distance calculation exponential - that would avoid something like having two points almost on top of each other, but far away from everything else, and having both make it through.