Apart from Gianlucas short and elegant solution I think it might be a good idea to reorder your data first. This way you can make sure that "interesting" points are not overlapped by "uninteresting" ones. Here a minimal example (using List of List instead of List of Rules):
data = RandomInteger[100, {100^2, 2}];
tdata0 = Tally[data];
tdata1 = GatherBy[SortBy[tdata0, Last], Last];
tdata2 = Transpose /@ tdata1;
tdata3 = First[Transpose@tdata2];
Here in this case we have 7 different occurences:
Length[tdata3]
(* Out: 7 *)
Now in the most simple case we can do
ListPlot[tdata3, AspectRatio -> Automatic,
PlotStyle -> {Directive[GrayLevel[0], PointSize[1 s]],
Directive[GrayLevel[.5], PointSize[2 s]],
Directive[RGBColor[0, 0, 1], PointSize[3 s]],
Directive[RGBColor[1, 0, 0], PointSize[4 s]],
Directive[RGBColor[1, 1, 0], PointSize[5 s]],
Directive[RGBColor[0, 0, 1], PointSize[6 s]],
Directive[RGBColor[0, 1, 0], PointSize[7 s]]} /. s -> .005]
which already results in:
Well, of course if you do not have that many data, then Gianlucas solution is surely preferable!