How can ATC distinguish planes that are stacked up in a holding pattern from each other?
Sometimes we can't.
While having two radar targets presented directly on top of each other is not really an issue (most radar presentation systems lets you move the data label around freely, so you can prevent overlap), the radar system itself can sometimes confuse two targets that are very close. A radar will search for aircraft by sending out a signal and waiting for the aircraft transponder to respond. When two aircraft are very close, they will receive the request from the radar almost at the same time, so their responses will be at the same time as well. The radar will receive the two replies on top of each other, which can result in garbling (see this related question).
In some situations, the radar software can also confuse two close targets, swapping the label between them, so aircraft A is presented to the controller as aircraft B and vice versa. We also sometimes see this close to an airport, where a departing aircraft can &quot;steal&quot; the label from an aircraft on short final, making it look like the departing aircraft is actually the one just about to land.
As a result of these issues, we are not allowed to use normal radar separation to individual aircraft in a holding stack. Instead, radar separation will be provided to a defined holding area, which is a geographical area established around a holding stack, large enough to ensure that anyone holding will remain within. Inside a holding stack, as you correctly noted, only vertical separation is used.
Mind you, most of the time, aircraft in a holding pattern are not flying directly on top of each other. That would require them to enter the holding at exactly the same time, fly at the exact same speed and turn at the exact same rate, which just doesn't happen. So the issues described above are not a problem most of the time, but they are common enough that we have specific procedures to mitigate the risks imposed.