The Ethics of Preparing for a Course Long Before Actually Taking it
IMO, there is no ethical problem with students preparing for a course in advance. As Moriarty notes in their answer, what matters is that the student learns the material, not when or how they learn it.
That said, there are (at least) two actual problems that your question touches upon:
the occasional problem of advanced (or self-taught) students taking beginner-level courses for "easy credits", and
the practical problem of teaching a course for students with a highly variable baseline experience level.
The first one could be considered unethical behavior in some circumstances. For example, let's say I'm a math major who decides to minor in biology, and the university happens to offer an "introductory math for biologists" course. If I was unscrupulous enough, and nothing specifically forbade me from doing so, I might be able to take that course and basically just show up for the exam, getting free biology credits for stuff I learned in first-year math.
(In fact, I freely admit to having done something similar myself on occasion. For example, one of the last courses I took as an undergrad, to make up the credits I needed to graduate, was a first-year "computer literacy" class that basically consisted of learning how to use a web browser, e-mail and a word processor. As I had already completed a minor in computer science, as well as worked for several years as a full-time software developer, I hardly need to mention I did not find it much of a challenge. Still, it got me the three extra credit points of "general studies" that I needed.)
It could also be argued that there is no problem: if you consider the credits to be awarded for knowing the material, then I clearly deserve them. On the other hand, if you consider the credits to be earned for learning something, then I clearly do not (as I already got credited for learning the same material once, back when I first learned it in math class).
More generally, issues like this can occur any time an institute offers multiple introductory-level courses covering essentially the same material (but possibly from a different angle) and does not specifically forbid students from taking more than one of them. When that happens, a student can effectively learn the material once, but get credited for it n times, where n is the number of such overlapping courses they can find.
The usual solution here is simply to try to find and close any such loopholes. Some possible methods for doing that include:
explicitly designating certain courses as equivalent to each other, so that a student can only receive credits for one of them, and
restricting certain very basic introductory courses, like the "math for biologists" example I gave above, only to students actually majoring in the target field (here, biology).
Also, if students are going to commit such shenanigans anyway, it can be argued that they should be allowed to demonstrate their competence in a separate exam, so that they don't need to waste time and classroom space, and skew the grade distribution, by actually sitting in a class they don't need.
As for the second problem I mentioned above, i.e. teaching a class where some students already know much more of the material than others, there are several distinct approaches that people may argue, depending on their general teaching philosophies. My personal suggestion, which I'd consider a "moderate" position, is to take a "triage" approach and mentally divide your students into distinct groups:
The advanced group consists of the students who already know much of the material, and just want to show their competence and get the official certificate for it. Some may be hoping to learn some interesting new tidbits, but they'll still pass the course even if they learn nothing new at all.
The learning group consists of those students who actually more or less match the intended level of the course: they know the prerequisites reasonably well, and are reasonably capable learners, but don't yet know the material you'll be covering. In many (but not all) courses, this group will make up the majority of the students, and they're the ones you should adjust your teaching pace for.
The struggling group consists of the students who lack some of the prerequisite knowledge the course assumes, or who are otherwise falling behind the rest of the class. They'll likely need remedial teaching to have any hope of passing the course. You should not have many students in this group; if you do, it may be sign that you're going too fast, and some of the students that should be in the "learning" group are falling behind.
It can be a temptation to focus on the "star" students in the advanced group, since they're the best in class, have the most interesting questions (if any), and generally appear to offer the most reward for the least effort. They're also the ones most likely to end up as future grad students in your field, which makes focusing on them even more tempting.
However, the advanced students are, by definition, not the ones the course is actually intended for, and they're not the ones you're really there to teach. Rather, your main goal with the advanced students (insofar as they come to class at all, rather than just taking the exam directly) is simply to ensure that they're not bored. There are several ways you can achieve this, such as:
giving the advanced students additional bonus exercises or projects that go beyond the standard syllabus, or letting them pursue their own side projects;
encouraging the more advanced students to help the less advanced ones;
encouraging students to come see you outside class if they'd like to learn more about something that sparked their interest; and
if you still cannot engage some students in class, letting them skip it if they already know the material.
As for the struggling students, there is an argument to be made that you, ideally, shouldn't have any, and that even a single student falling behind is a sign that you should slow down until they can catch up. Essentially, this approach amounts to lumping the "learning" and "struggling" groups together, adjusting your pace to the tail end of that combined group, and treating any students who progress faster as "advanced".
While there is some merit to this approach, it can also be taken too far. Especially in higher education, it is often simply not possible to set the pace by the slowest students in class, and still have enough time to cover all the material in the allotted time. Instead, as an alternative to simply letting these students fail, it may be more effective to set the in-class pace by the majority of the class, and to focus specific remedial efforts (such as individual tutoring, possibly by some of the more advanced students) on those that need it.
Of course, even this won't always help, and sometimes you may simply have to let a student fail. In particular, it's important to learn to distinguish students who'd like to learn, but have a hard time doing so, from those who are simply too lazy or disinterested to learn. The former group can be helped; the latter cannot.
A student takes a course to prove he learned the stuff in the syllabus. He/she passes the course, and then has official certification that he knows that stuff.
Who cares when he learned it?
The trickiest part is keeping the course interesting for the high-flyers, without alienating the less able (or less knowledgeable) class members.
The goal of a university course is education on a particular topic. Students who study before the class are educating themselves on that topic. Students who don't study before the class are, hopefully, being educated by the teacher on that topic. Both of these things achieve the goal.
Frankly, if you have even the slightest suspicion that it is unethical for your students to educate themselves, you are in the wrong place. There is no such thing as "too educated" in academia.