Reading 16 voltages accurately with three decimals on Arduino
I am going to suggest a 50V-rated switch per cell, connecting any one cell at a time to a single attenuator of about 10:1 (if your ADC can tolerate 5V in) and an ADC of at least 16 bits real accuracy.

Single attenuator. Attenuators are only as accurate as their resistors - typically 1 % but for a price you can buy resistors trimmed or matched to 0.1% or better. If you measure both ends of a cell with the same attenuator, both measurements have the same percentage error, so the error is largely cancelled out. And as there is only one attenuator, the impact of expensive components is minimal.

50V-rated switch. Possibly a reed relay per cell. Simple and avoids worrying about MOSFET ratings or gate drive requirements. Connect a medium value resistor (say 100R or 1k) in series with each switch to limit current if you inadvertently enable two switches at once. Perhaps make that a feature, and enable switches at both ends of a cell if you need to actively balance cells in a controlled manner.

16-bit or better ADC. To read 1mv per cell across 50V, you need 50,000 counts, i.e. 16 bits giving you 65536. Your proposed 24-bit ADC should be good for about 20 bits in practice, though you need to pay attention to error sources (Vref stability, where the ground currents run, etc) to get close to this in practice.

To calculate a single cell's voltage, read the tap at one end, then the other end, and subtract. (Re-read the first end as a consistency check). I recommend being able to read both ends of every cell, so you need 17 taps not 16.

The alternative is a fully floating measurement system, which I think will be more complex.