Normally this is used for function calls to contracts. An exchange could make a contract that lets the user put in their userId when sending eth, and then everybody would be sending to the same address while still being identifiable. It would even be possible to reject deposits which do not include the userId, or which have an unknown userId.
I think the main reason exchanges don't do this is that they deal with lots of cryptocurrencies, so they use the simplest method that works for all of them: just make a unique deposit address for each user.